'''
第四章 异常处理和文件读写
在语法上和功能上没问题的程序也未必能运行成功，因为程序的运行环境存在各种不确定的因素。
比如，remove列表元素时，元素不存在，系统会抛出错误；文件读取不到时，系统会抛出错误；链接数据库失败；断网....等等
如果没有错误捕获机制，系统就会崩溃，程序终止。
作为开发者，期望：
  1. 看到错误细节
  2. 程序继续进行，而不是中止
  所以，需要用到Python的异常处理机制：捕获错误，返回错误细节。
  异常不是语法错误。
'''
from sqlite3 import DatabaseError
import warnings


print('start working')
myList = [1,2,3,4]
try:
  myList.remove(5)
except:
  print(myList)
  print('remove error')
print('continue working')

# 不同的异常处理类，默认Except类, except IndexError: 指定参数类
'''
IndexError 索引出错时会触发
ValueError 参数类型正确，但返回值不符合预期会触发
TypeError 函数参数类型不正确时会触发
ZeroDivisionError 除零异常
AttributeError 引发属性错误时触发
OSError 无法完成操作系统级别的任务时触发，比如无法打开文件
FloatingPointError 浮点类计算错误
OverflowError 数值运算时超过此种类型数值的最大范围
UnicodeTranslateError Unicode转换时出错
DatabaseError 数据库连接错误
FileExistsError 文件找不到
'''

# 在except中处理多个类型的异常
print('=========START====')
try:
  myList.remove(5)
  print(myList[9])
except(IndexError, ValueError, FileExistsError) as e:
  print('remove error')
  print(e)

# 用raise语句直接抛出异常（前面的demo都是自动触发的异常）
print('=========START====')
def divide(x,y):
  if y==0:
    raise Exception('Error: Divisor is 0')
  try:
    return x/y
  except(TypeError):
    raise Exception('Error: Parameters Type Error')

try:
 divide(2, 0)
except(Exception) as e:
  print(e)

# finally从句
print('=========START====')
try:
 divide(2, 0)
#  divide(2, 1)
except(Exception) as e:
  print(e)
finally:
  print('FINALLY')

# 在实际业务处理过程中，尽量缩小异常监控范围，这样就能更精确的定位到异常的位置

# 尽量缩小异常的影响范围：比如两个并行业务，其中一个出错，尽量不要影响另一个正常执行

# 在合适的场景使用告警（Warning）：
# warnings.warn('Hello')

print('=============START=========')
'''
通过IO读写文件，Python的标准库就提供了文件读写的方法。
r 读取模式
w 写入模式
r+ 读写模式，从头开始写，保持原文件中没被覆盖的内容
w+ 读写模式，写的时候文件存在，就清空，从头开始写
a 附加写模式。文件存在从文末尾开始写，否则新建文件
a+ 附加读写模式。
b 二进制模式，而非文本模式
'''
f = open('../docs/hello.txt', 'a+') # 'r'默认文件打开模式--read读取
line = f.readline()
while line:
  print(line, end='')
  line = f.readline()
# 写入
f.write('HAHA\r')
f.write('HAHA222\n')
# 文件对象会占用系统资源，而操作系统同时打开的文件数量是有限的，因此在用完文件后，记得close关闭文件
# 写文件时，系统不会立刻写，而是放到缓存中，当调用close时，把缓存内容写到文件中
f.close()

'''
可以看看一些移动文件、复制文件、新建文件、删除文件、读取zip、读取csv文件等等例子
'''
